home *** CD-ROM | disk | FTP | other *** search
-
- static char rcsid[] = "@(#)$Id: parsarpdat.c,v 5.2 1993/04/12 02:16:32 syd Exp $";
-
- /*******************************************************************************
- * The Elm Mail System - $Revision: 5.2 $ $State: Exp $
- *
- * Copyright (c) 1993 USENET Community Trust
- *******************************************************************************
- * Bug reports, patches, comments, suggestions should be sent to:
- *
- * Syd Weinstein, Elm Coordinator
- * elm@DSI.COM dsinc!elm
- *
- *******************************************************************************
- * $Log: parsarpdat.c,v $
- * Revision 5.2 1993/04/12 02:16:32 syd
- * Fix year handling bug in date(1) time formats.
- * From: chip@chinacat.unicom.com (Chip Rosenthal)
- *
- * Revision 5.1 1993/01/19 04:46:21 syd
- * Initial Checkin
- *
- *
- ******************************************************************************/
-
-
- #include "headers.h"
- #include <ctype.h>
-
-
- /*
-
- Quoting from RFC 822:
- 5. DATE AND TIME SPECIFICATION
-
- 5.1. SYNTAX
-
- date-time = [ day "," ] date time ; dd mm yy
- ; hh:mm:ss zzz
-
- day = "Mon" / "Tue" / "Wed" / "Thu"
- / "Fri" / "Sat" / "Sun"
-
- date = 1*2DIGIT month 2DIGIT ; day month year
- ; e.g. 20 Jun 82
-
- month = "Jan" / "Feb" / "Mar" / "Apr"
- / "May" / "Jun" / "Jul" / "Aug"
- / "Sep" / "Oct" / "Nov" / "Dec"
-
- time = hour zone ; ANSI and Military
-
- hour = 2DIGIT ":" 2DIGIT [":" 2DIGIT]
- ; 00:00:00 - 23:59:59
-
- zone = "UT" / "GMT" ; Universal Time
- ; North American : UT
- / "EST" / "EDT" ; Eastern: - 5/ - 4
- / "CST" / "CDT" ; Central: - 6/ - 5
- / "MST" / "MDT" ; Mountain: - 7/ - 6
- / "PST" / "PDT" ; Pacific: - 8/ - 7
- / 1ALPHA ; Military: Z = UT;
- ; A:-1; (J not used)
- ; M:-12; N:+1; Y:+12
- / ( ("+" / "-") 4DIGIT ) ; Local differential
- ; hours+min. (HHMM)
- */
-
-
- int parse_arpa_date(str, entry)
- char *str;
- struct header_rec *entry;
- {
- /*
- * Parse a date field in either RFC-822 or Unix date(1) format.
- * We will fill in the "time_zone", "tz_offset", and "time_sent"
- * parts of the "entry" structure. Return TRUE on success, FALSE
- * on failure.
- */
-
- char field[STRING], save_tz[STRING];
- int month, day, year, hours, mins, secs, tz, len, i;
-
- /*
- * Since this is an RFC-822 field, there might be parenthetical
- * comments. Yank them out. Note that strip_parens() returns
- * a pointer to static data.
- */
- str = strip_parens(str);
-
- /*
- * The first field is an optional day of the week. If it exists
- * it is supposed to have a trailing comma by RFC-822, but we won't
- * complain if it doesn't. If the date string was generated by
- * the Unix date(1) command then it won't have the comma. We don't
- * do anything with this information, just skip over it if it exists.
- */
- if ((len = get_word(str, 0, field, sizeof(field))) < 0)
- goto failed;
- if (cvt_dayname_to_daynum(field, &i))
- str += len;
-
- /*
- * Peek at the next character to determine what format to
- * parse the rest of the line as.
- */
- while (isspace(*str))
- ++str;
- if (!isdigit(*str)) {
-
- /*
- * Parse the line in Unix date(1) format. The syntax is:
- *
- * month day hh:mm:ss [tz] year
- *
- * e.g. "Jun 21 06:45:44 CDT 1989". The timezone is optional.
- */
-
- dprint(7, (debugfile,
- "parse_arpa_date parsing \"%s\" in time(1) format\n", str));
-
- /* <month> */
- if ((len = get_word(str, 0, field, sizeof(field))) < 0 ||
- !cvt_monthname_to_monthnum(field, &month))
- goto failed;
- str += len;
-
- /* <day> */
- if ((len = get_word(str, 0, field, sizeof(field))) < 0 ||
- (day = atonum(field)) < 0)
- goto failed;
- str += len;
-
- /* <hh:mm:ss> */
- if ((len = get_word(str, 0, field, sizeof(field))) < 0 ||
- !cvt_timestr_to_hhmmss(field, &hours, &mins, &secs))
- goto failed;
- str += len;
-
- /* optional <tz> */
- save_tz[0] = save_tz[1] = '\0';
- tz = 0;
- while ((len = get_word(str, 0, field, sizeof(field))) > 0 &&
- cvt_timezone_to_offset(field, &i)) {
- (void) strcat(save_tz, " ");
- (void) strcat(save_tz, field);
- tz += i;
- str += len;
- }
-
- /* <year> */
- if ((len = get_word(str, 0, field, sizeof(field))) < 0 ||
- (year = atonum(field)) < 0)
- goto failed;
- str += len;
-
- /* there might be more...but we ignore it */
-
- } else {
-
- /*
- * Parse the line in RFC-822 format. The syntax is:
- *
- * day month year hh:mm:ss zone
- *
- * e.g. "17 Nov 92 23:34:25 CST".
- */
-
- dprint(7, (debugfile,
- "parse_arpa_date parsing \"%s\" in RFC-822 format\n", str));
-
- /* <day> */
- if ((len = get_word(str, 0, field, sizeof(field))) < 0 ||
- (day = atonum(field)) < 0)
- goto failed;
- str += len;
-
- /* <month> */
- if ((len = get_word(str, 0, field, sizeof(field))) < 0 ||
- !cvt_monthname_to_monthnum(field, &month))
- goto failed;
- str += len;
-
- /* <year> */
- if ((len = get_word(str, 0, field, sizeof(field))) < 0 ||
- !cvt_yearstr_to_yearnum(field, &year))
- goto failed;
- str += len;
-
- /* <hh:mm:ss> */
- if ((len = get_word(str, 0, field, sizeof(field))) < 0 ||
- !cvt_timestr_to_hhmmss(field, &hours, &mins, &secs))
- goto failed;
- str += len;
-
- /* <tz> - silently ignore bogus or missing timezones */
- save_tz[0] = save_tz[1] = '\0';
- tz = 0;
- while ((len = get_word(str, 0, field, sizeof(field))) > 0 &&
- cvt_timezone_to_offset(field, &i)) {
- (void) strcat(save_tz, " ");
- (void) strcat(save_tz, field);
- tz += i;
- str += len;
- }
-
- /* there might be more...but we ignore it */
-
- }
-
- strfcpy(entry->time_zone, save_tz+1, sizeof(entry->time_zone));
- entry->tz_offset = tz*60;
- entry->time_sent = make_gmttime(year, month, day, hours, mins-tz, secs);
-
- dprint(7, (debugfile, " year=%d month=%d day=%d\n", year, month, day));
- dprint(7, (debugfile, " hours=%d mins=%d secs=%d tz=%d\n",
- hours, mins, secs, tz));
- dprint(7, (debugfile, " return success\n"));
- return TRUE;
-
- failed:
- dprint(4, (debugfile, "parse_arpa_date failed at \"%s\"\n",
- (len <= 0 ? "<premature eol>" : field)));
- return FALSE;
- }
-
- #ifdef _TEST
- int debug = 9999;
- FILE *debugfile = stderr;
- main()
- {
- struct header_rec hdr;
- char buf[1024];
- while (gets(buf) != NULL) {
- if (!parse_arpa_date(buf, &hdr))
- fprintf(stderr, "FAIL %s\n", buf);
- else {
- fprintf(stderr, "OK %s\n", buf);
- fprintf(stderr, "time_zone=%s tz_offset=%d time_sent=%ld\n",
- hdr.time_zone, hdr.tz_offset, hdr.time_sent);
- }
- putc('\n', stderr);
- }
- exit(0);
- }
- #endif
-
-